﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.Contracts;

namespace YasharEl.Infrastructure.ExceptionHandling
{
    public class WrapHandler : IExceptionHandler
    {
        #region Fields

        private readonly Type wrapExceptionType;
        private string exceptionMessage;
        private string exceptionMessageResourceKey;

        #endregion

        #region Constructors

        public WrapHandler(string exceptionMessage,
            string exceptionMessageResourceKey,
            IMessageTranslator messageTranslator,
            Type wrapExceptionType)
        {
            Contract.Requires<ArgumentNullException>(wrapExceptionType != null, "wrapExceptionType could not be null.");
            Contract.Requires<ArgumentNullException>(messageTranslator != null, "messageTranslator could not be null.");

            this.wrapExceptionType = wrapExceptionType;
            this.exceptionMessage = exceptionMessage;
            this.exceptionMessageResourceKey = exceptionMessageResourceKey;

            if (!string.IsNullOrEmpty(exceptionMessageResourceKey))
            {
                this.exceptionMessage = messageTranslator.Translate(exceptionMessageResourceKey);
            }
        }

        #endregion

        #region Properties

        /// <summary>
        /// The type of exception to wrap.
        /// </summary>
        public Type WrapExceptionType
        {
            get { return wrapExceptionType; }
        }

        /// <summary>
        /// Gets the message for the new exception.
        /// </summary>
        public string ExceptionMessage
        {
            get { return exceptionMessage; }
        }

        #endregion

        #region IExceptionHandler Implementations

        public Exception HandleException(Exception exception, Guid handlingInstanceId)
        {
            return WrapException(
                exception,
                ExceptionUtility.FormatExceptionMessage(ExceptionMessage, handlingInstanceId));
        }

        #endregion

        #region Private Methods

        private Exception WrapException(Exception originalException, string wrapExceptionMessage)
        {
            object[] extraParameters = new object[2];
            extraParameters[0] = wrapExceptionMessage;
            extraParameters[1] = originalException;
            return (Exception)Activator.CreateInstance(wrapExceptionType, extraParameters);
        }

        #endregion
    }
}
